/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package util;

import java.awt.*;
import javax.swing.*;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import marvin.gui.MarvinImagePanel;
import marvin.image.MarvinImage;
import marvin.image.MarvinImageMask;
import marvin.plugin.MarvinImagePlugin;
import marvin.util.MarvinAttributes;
import marvin.util.MarvinPluginLoader;

/**
 *
 * @author Psiak
 */
public class Normalization extends javax.swing.JFrame {

    private static final int FACE_WIDTH = 125;
    private static final int FACE_HEIGHT = 150;
    private static MarvinImagePlugin imagePlugin;
    private static MarvinImage image;
    public static MarvinImagePanel imagePanelNew;

        final private static int WHITE = 0x00FFFFFF;
    final private static int BLACK = 0x00000000;
    
    
    
    public static BufferedImage MedianFilter(BufferedImage obrazek, int antrybut) {
        image = BufferedImagenaMarvinImage(obrazek);
        imagePlugin = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.statistical.median.jar");
        imagePlugin.setAttribute("size", antrybut);
        imagePlugin.process(image, image, null, MarvinImageMask.NULL_MASK, false);
        image.update();
        return MarvinImagenaBufferedImage(image);
    }

    public static BufferedImage BrightnessContrast(BufferedImage obrazek, int antrybut1, int antrybut2) {
        if (obrazek == null) {
            return new BufferedImage(32, 32, BufferedImage.TYPE_3BYTE_BGR);
        } else {
            MarvinImage imageIn = BufferedImagenaMarvinImage(obrazek);
            MarvinImage imageOut = BufferedImagenaMarvinImage(obrazek);
            double r, g, b;
            double l_brightness = (Integer) antrybut1;
            double l_contrast = (Integer) antrybut2;
            l_contrast = Math.pow((127 + l_contrast) / 127, 2);
            for (int x = 0; x < imageIn.getWidth(); x++) {
                for (int y = 0; y < imageIn.getHeight(); y++) {
                    r = imageIn.getIntComponent0(x, y);
                    g = imageIn.getIntComponent1(x, y);
                    b = imageIn.getIntComponent2(x, y);

                    r += (1 - (r / 255)) * l_brightness;
                    g += (1 - (g / 255)) * l_brightness;
                    b += (1 - (b / 255)) * l_brightness;
                    if (r < 0) {
                        r = 0;
                    }
                    if (r > 255) {
                        r = 255;
                    }
                    if (g < 0) {
                        g = 0;
                    }
                    if (g > 255) {
                        g = 255;
                    }
                    if (b < 0) {
                        b = 0;
                    }
                    if (b > 255) {
                        b = 255;
                    }

                    imageOut.setIntColor(x, y, (int) r, (int) g, (int) b);
                }
            }
            // Contrast
            for (int x = 0; x < imageIn.getWidth(); x++) {
                for (int y = 0; y < imageIn.getHeight(); y++) {
                    r = imageOut.getIntComponent0(x, y);
                    g = imageOut.getIntComponent1(x, y);
                    b = imageOut.getIntComponent2(x, y);


                    r /= 255.0;
                    r -= 0.5;
                    r *= l_contrast;
                    r += 0.5;
                    r *= 255.0;

                    g /= 255.0;
                    g -= 0.5;
                    g *= l_contrast;
                    g += 0.5;
                    g *= 255.0;

                    b /= 255.0;
                    b -= 0.5;
                    b *= l_contrast;
                    b += 0.5;
                    b *= 255.0;


                    if (r < 0) {
                        r = 0;
                    }
                    if (r > 255) {
                        r = 255;
                    }
                    if (g < 0) {
                        g = 0;
                    }
                    if (g > 255) {
                        g = 255;
                    }
                    if (b < 0) {
                        b = 0;
                    }
                    if (b > 255) {
                        b = 255;
                    }

                    imageOut.setIntColor(x, y, (int) r, (int) g, (int) b);
                }
            }
            imageOut.update();
            return MarvinImagenaBufferedImage(imageOut);
        }
    }

    public static BufferedImage binaringImage(BufferedImage image, byte parameter){
        BufferedImage bf=new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
       
         for (int x = 0; x < bf.getWidth(); x++) {
                for (int y = 0; y < bf.getHeight(); y++) {
                  
                    if((byte)image.getRGB(x, y)>parameter){
                    bf.setRGB(x, y, BLACK);
                    }else{
                    bf.setRGB(x, y, WHITE);
                    }
                }
         }
        return bf;
    }
    
    public static BufferedImage Binarization(BufferedImage obrazek, int antrybut) {
        //MarvinAttributes attributes=new MarvinAttributes();
        MarvinImageMask mask = new MarvinImageMask();
        MarvinImage imageOut = BufferedImagenaMarvinImage(obrazek);
        MarvinImage imageIn = BufferedImagenaMarvinImage(obrazek);
        //MarvinAttributes attributesOut= new MarvinAttributes();

        //attributes.set("threshold", 125);
        imagePlugin.process(imageIn, imageOut, null, mask, false);

        boolean[][] l_arrMask = mask.getMaskArray();

        for (int y = 0; y < imageIn.getHeight(); y++) {
            for (int x = 0; x < imageIn.getWidth(); x++) {
                if (l_arrMask != null && !l_arrMask[x][y]) {
                    continue;
                }

                if (imageIn.getIntComponent0(x, y) < antrybut) {
                    imageOut.setIntColor(x, y, 0, 0, 0);
                } else {
                    imageOut.setIntColor(x, y, 255, 255, 255);
                }
            }
        }
        imageOut.update();
        return MarvinImagenaBufferedImage(imageOut);
    }

    public static BufferedImage Erosion(BufferedImage obrazek) {
        boolean matrix[][] = null;
        MarvinAttributes attrOut = null;
        MarvinImageMask mask = null;
        image = BufferedImagenaMarvinImage(obrazek);
        imagePlugin = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.morphological.erosion.jar");
        imagePlugin.setAttribute("matrix", matrix);
        matrix = (boolean[][]) imagePlugin.getAttribute("matrix");
        imagePlugin.process(image, image, attrOut, mask, false);
        MarvinImage.copyColorArray(image, image);
        image.update();
        return MarvinImagenaBufferedImage(image);
    }

    private static BufferedImage MarvinImagenaBufferedImage(MarvinImage obrazek) {
        return obrazek.getBufferedImage();
    }

    private static MarvinImage BufferedImagenaMarvinImage(BufferedImage obrazek) {
        if (obrazek == null) {
            return null;
        } else {
            image = new MarvinImage(obrazek.getWidth(), obrazek.getHeight());
            image.setBufferedImage(obrazek);
            return image;
        }
    }

    public static BufferedImage changeBrightness(BufferedImage inImage, int increasingFactor) {

        //size of input image
        int w = inImage.getWidth();
        int h = inImage.getHeight();

        //Pixel by pixel navigation loop
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {

                //get the RGB component of input imge pixel
                Color color = new Color(inImage.getRGB(i, j));

                int r, g, b;

                //change the value of each component
                r = color.getRed() + increasingFactor;
                g = color.getGreen() + increasingFactor;
                b = color.getBlue() + increasingFactor;


                //r,g,b values which are out of the range 0 to 255 should set to 0 or 255
                if (r >= 256) {
                    r = 255;
                } else if (r < 0) {
                    r = 0;
                }

                if (g >= 256) {
                    g = 255;
                } else if (g < 0) {
                    g = 0;
                }

                if (b >= 256) {
                    b = 255;
                } else if (b < 0) {
                    b = 0;
                }

                //set output image pixel component
                inImage.setRGB(i, j, new Color(r, g, b).getRGB());

            }
        }

        return inImage;
    }

    public static BufferedImage brightness(BufferedImage obrazek, int antrybut) {
        int matryca[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        int alpha[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                int color = obrazek.getRGB(j, i);
                alpha[j][i] = (color >> 24) & 255;
                int lum = (color >> 16) & 255;
                int lum1 = (color >> 8) & 255;
                int lum2 = (color) & 255;
                int luminancja = (int) (0.3 * lum + 0.59 * lum1 + 0.11 * lum2);
                matryca[j][i] = luminancja;
            }
        }
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                if (matryca[j][i] == 255) {
                }

                matryca[j][i] = (int) (matryca[j][i] + (antrybut - 127));

            }
        }
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                if (matryca[j][i] > 255) {
                    matryca[j][i] = 255;
                }
                if (matryca[j][i] < 0) {
                    matryca[j][i] = 0;
                }

            }
        }
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {

                obrazek.setRGB(j, i, ((alpha[j][i] << 24) + matryca[j][i] << 16) + (matryca[j][i] << 8) + (matryca[j][i]));

            }
        }
        return obrazek;
    }

    public static BufferedImage scale_to_dimension(BufferedImage obrazek, int nowy_rozmiar_szerokosc, int nowy_rozmiar_wysokosc) {
        if (nowy_rozmiar_szerokosc == 0 || nowy_rozmiar_wysokosc == 0) {
            return obrazek;
        } else {
            int w1 = obrazek.getWidth();
            int h1 = obrazek.getHeight();
            int l1 = 0, l2 = 0;
            int[] tablica = new int[obrazek.getWidth() * obrazek.getHeight()];
            for (int y = 0; y < obrazek.getHeight(); y++) {
                for (int x = 0; x < obrazek.getWidth(); x++) {
                    tablica[l1] = obrazek.getRGB(x, y);
                    l1++;
                }
            }

            int w2 = nowy_rozmiar_szerokosc;
            int h2 = nowy_rozmiar_wysokosc;

            int[] tablica1 = new int[w2 * h2];
            int x_mnoznik = (int) ((w1 << 16) / w2);
            int y_mnoznik = (int) ((h1 << 16) / h2);
            int x2, y2;
            for (int i = 0; i < h2; i++) {
                for (int j = 0; j < w2; j++) {
                    x2 = ((j * x_mnoznik) >> 16);
                    y2 = ((i * y_mnoznik) >> 16);
                    tablica1[(i * w2) + j] = tablica[(y2 * w1) + x2];
                }
            }

            BufferedImage img1 = new BufferedImage(nowy_rozmiar_szerokosc, nowy_rozmiar_wysokosc, BufferedImage.TYPE_INT_RGB);
            for (int i = 0; i < nowy_rozmiar_wysokosc; i++) {
                for (int j = 0; j < nowy_rozmiar_szerokosc; j++) {
                    img1.setRGB(j, i, tablica1[l2]);
                    l2++;
                }
            }
            return img1;
        }
    }

    Normalization() {
    }

    public BufferedImage rozmiar_szarosc_obrazek(BufferedImage im) // resize to at least a standard size, then convert to grayscale
    {
        // resize the image so *at least* FACE_WIDTH*FACE_HEIGHT size
        int imWidth = im.getWidth();
        int imHeight = im.getHeight();


        double widthScale = FACE_WIDTH / ((double) imWidth);
        double heightScale = FACE_HEIGHT / ((double) imHeight);
        double scale = (widthScale > heightScale) ? widthScale : heightScale;

        int nWidth = (int) Math.round(imWidth * scale);
        int nHeight = (int) Math.round(imHeight * scale);

        // convert to grayscale while resizing
        BufferedImage grayIm = new BufferedImage(nWidth, nHeight,
                BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g2 = grayIm.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.drawImage(im, 0, 0, nWidth, nHeight, 0, 0, imWidth, imHeight, null);
        g2.dispose();


        return grayIm;
    }  // end of resizeImage()

    public struktura_detekcja_oczu detekcja_oczu_gradient(BufferedImage obrazek) {
//pozioma kreska lewa

        int wektory_poziome[] = new int[(obrazek.getHeight())];
        int wartosc1, wartosc2;
        Point lewe;
        Point prawe;
        int lewe_polozenie_y;
        int prawe_polozenie_y;

        for (int w = 0; w < obrazek.getHeight(); w++) {

            for (int k = 0; k < obrazek.getWidth() / 2; k++) {
                if (k != obrazek.getWidth() - 1) {
                    wartosc1 = (byte) obrazek.getRGB(k, w);
                    wartosc2 = (byte) obrazek.getRGB(k + 1, w);
                    wektory_poziome[w] = wektory_poziome[w] + Math.abs((wartosc1 + (int) 128) - (wartosc2 + (int) 128));
                }
            }
        }

        int max = -255;
        int max_wektor = 0;

        for (int i = 0; i < wektory_poziome.length; i++) {
            if (wektory_poziome[i] > max) {

                max = wektory_poziome[i];
                max_wektor = i;
            }
        }

        lewe_polozenie_y = max_wektor;

        for (int i = 0; i < obrazek.getWidth() / 2; i++) {
            obrazek.setRGB(i, max_wektor, (byte) 0x00000000);
        }

        for (int i = 0; i < wektory_poziome.length; i++) {
            wektory_poziome[i] = 0;
        }


//pozioma kreska prawa

        for (int w = 0; w < obrazek.getHeight(); w++) {

            for (int k = obrazek.getWidth() / 2; k < obrazek.getWidth(); k++) {
                if (k != obrazek.getWidth() - 1) {
                    wartosc1 = (byte) obrazek.getRGB(k, w);
                    wartosc2 = (byte) obrazek.getRGB(k + 1, w);
                    wektory_poziome[w] = wektory_poziome[w] + Math.abs((wartosc1 + (int) 128) - (wartosc2 + (int) 128));

                }
            }
        }

        max = -255;
        max_wektor = 0;

        for (int i = 0; i < wektory_poziome.length; i++) {
            if (wektory_poziome[i] > max) {

                max = wektory_poziome[i];
                max_wektor = i;
            }
        }

        prawe_polozenie_y = max_wektor;

        for (int i = obrazek.getWidth() / 2; i < obrazek.getWidth(); i++) {
            obrazek.setRGB(i, max_wektor, (byte) 0x00000000);
        }







//pionowe
        int wektory_pionowe[] = new int[obrazek.getWidth()];

        for (int s = 0; s < obrazek.getWidth(); s++) {

            for (int w = 0; w < obrazek.getHeight(); w++) {
                if (w != obrazek.getHeight() - 1) {
                    wartosc1 = (byte) obrazek.getRGB(s, w);
                    wartosc2 = (byte) obrazek.getRGB(s, w + 1);
                    wektory_pionowe[s] = wektory_pionowe[s] + Math.abs((wartosc1 + (int) 128) - (wartosc2 + (int) 128));

                }
            }

        }

//lewa
        max = -256;
        for (int i = 0; i < wektory_pionowe.length / 2; i++) {
            if (wektory_pionowe[i] > max) {
                max = wektory_pionowe[i];
                max_wektor = i;
            }
        }

        lewe = new Point(max_wektor, lewe_polozenie_y);

        for (int i = 0; i < obrazek.getHeight(); i++) {
            obrazek.setRGB(max_wektor, i, (byte) 0x00000000);
        }


//prawa
        max = -256;
        for (int i = wektory_pionowe.length / 2; i < wektory_pionowe.length; i++) {
            if (wektory_pionowe[i] > max) {
                max = wektory_pionowe[i];
                max_wektor = i;
            }
        }

        prawe = new Point(max_wektor, prawe_polozenie_y);

        for (int i = 0; i < obrazek.getHeight(); i++) {
            obrazek.setRGB(max_wektor, i, (byte) 0x00000000);
        }



        struktura_detekcja_oczu sdo = new struktura_detekcja_oczu();
        sdo.odleglosc = (int) Math.round(Math.sqrt((((prawe.x - lewe.x) * (prawe.x - lewe.x)) + ((prawe.y - lewe.y) * (prawe.y - lewe.y)))));
        sdo.lewy = lewe;
        sdo.prawy = prawe;
        sdo.obrazek = obrazek;
        sdo.kat = Math.toDegrees(Math.atan2(prawe.x - lewe.x, prawe.y - lewe.y));

        return sdo;
    }

    public struktura_detekcja_oczu detekcja_nosa_gradient(BufferedImage obrazek) {
//pozioma kreska lewa

        int wektory_poziome[] = new int[(obrazek.getHeight())];
        int wartosc1, wartosc2;
        Point lewe;
        Point prawe;
        int lewe_polozenie_y;
        int prawe_polozenie_y;

        for (int w = 0; w < obrazek.getHeight(); w++) {

            for (int k = 0; k < obrazek.getWidth() / 2; k++) {
                if (k != obrazek.getWidth() - 1) {
                    wartosc1 = (byte) obrazek.getRGB(k, w);
                    wartosc2 = (byte) obrazek.getRGB(k + 1, w);
                    wektory_poziome[w] = wektory_poziome[w] + Math.abs((wartosc1 + (int) 128) - (wartosc2 + (int) 128));
                }
            }
        }

        int max = -255;
        int max_wektor = 0;

        for (int i = 0; i < wektory_poziome.length; i++) {
            if (wektory_poziome[i] > max) {

                max = wektory_poziome[i];
                max_wektor = i;
            }
        }

        lewe_polozenie_y = max_wektor;

        for (int i = 0; i < obrazek.getWidth() / 2; i++) {
            obrazek.setRGB(i, max_wektor, (byte) 0x00000000);
        }

        for (int i = 0; i < wektory_poziome.length; i++) {
            wektory_poziome[i] = 0;
        }


//pozioma kreska prawa

        for (int w = 0; w < obrazek.getHeight(); w++) {

            for (int k = obrazek.getWidth() / 2; k < obrazek.getWidth(); k++) {
                if (k != obrazek.getWidth() - 1) {
                    wartosc1 = (byte) obrazek.getRGB(k, w);
                    wartosc2 = (byte) obrazek.getRGB(k + 1, w);
                    wektory_poziome[w] = wektory_poziome[w] + Math.abs((wartosc1 + (int) 128) - (wartosc2 + (int) 128));

                }
            }
        }

        max = -255;
        max_wektor = 0;

        for (int i = 0; i < wektory_poziome.length; i++) {
            if (wektory_poziome[i] > max) {

                max = wektory_poziome[i];
                max_wektor = i;
            }
        }

        prawe_polozenie_y = max_wektor;

        for (int i = obrazek.getWidth() / 2; i < obrazek.getWidth(); i++) {
            obrazek.setRGB(i, max_wektor, (byte) 0x00000000);
        }







//pionowe
        int wektory_pionowe[] = new int[obrazek.getWidth()];

        for (int s = 0; s < obrazek.getWidth(); s++) {

            for (int w = 0; w < obrazek.getHeight(); w++) {
                if (w != obrazek.getHeight() - 1) {
                    wartosc1 = (byte) obrazek.getRGB(s, w);
                    wartosc2 = (byte) obrazek.getRGB(s, w + 1);
                    wektory_pionowe[s] = wektory_pionowe[s] + Math.abs((wartosc1 + (int) 128) - (wartosc2 + (int) 128));

                }
            }

        }

//lewa
        max = -256;
        for (int i = 0; i < wektory_pionowe.length / 2; i++) {
            if (wektory_pionowe[i] > max) {
                max = wektory_pionowe[i];
                max_wektor = i;
            }
        }

        lewe = new Point(max_wektor, lewe_polozenie_y);

        for (int i = 0; i < obrazek.getHeight(); i++) {
            obrazek.setRGB(max_wektor, i, (byte) 0x00000000);
        }


//prawa
        max = -256;
        for (int i = wektory_pionowe.length / 2; i < wektory_pionowe.length; i++) {
            if (wektory_pionowe[i] > max) {
                max = wektory_pionowe[i];
                max_wektor = i;
            }
        }

        prawe = new Point(max_wektor, prawe_polozenie_y);

        for (int i = 0; i < obrazek.getHeight(); i++) {
            obrazek.setRGB(max_wektor, i, (byte) 0x00000000);
        }



        struktura_detekcja_oczu sdo = new struktura_detekcja_oczu();
        sdo.odleglosc = (int) Math.round(Math.sqrt((((prawe.x - lewe.x) * (prawe.x - lewe.x)) + ((prawe.y - lewe.y) * (prawe.y - lewe.y)))));
        sdo.lewy = lewe;
        sdo.prawy = prawe;
        sdo.obrazek = obrazek;
        sdo.kat = Math.toDegrees(Math.atan2(prawe.x - lewe.x, prawe.y - lewe.y));

        return sdo;
    }

    public BufferedImage rozciagniecie_histogramu(BufferedImage obrazek, float wart_max) {
        //x y



        int matryca[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        int alpha[][] = new int[obrazek.getWidth()][obrazek.getHeight()];

        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                int color = obrazek.getRGB(j, i);
                alpha[j][i] = (color >> 24) & 255;
                int lum = (color >> 16) & 255;
                int lum1 = (color >> 8) & 255;
                int lum2 = (color) & 255;
                int luminancja = (int) (0.3 * lum + 0.59 * lum1 + 0.11 * lum2);
                matryca[j][i] = luminancja;
            }
        }


        //wyznaczenie maksymalnej wartosci
        int max = 0;
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                if (matryca[j][i] > max) {
                    max = matryca[j][i];
                }
            }
        }
//
        //wyznaczenie minimalnej wartosci
        int min = 255;
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                if (matryca[j][i] < min) {
                    min = matryca[j][i];
                }
            }
        }



        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                matryca[j][i] = (int) (((float) wart_max / (float) (max - min)) * (float) ((matryca[j][i]) - min));
            }
        }

        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {

                obrazek.setRGB(j, i, ((alpha[j][i] << 24) + matryca[j][i] << 16) + (matryca[j][i] << 8) + (matryca[j][i]));

            }
        }

        return obrazek;
    }

    public static BufferedImage scaleGray(BufferedImage img, int type) /* Scale the image and convert it to grayscale. Scaling makes
     the image smaller and so faster to process, and Haar detection
     requires a grayscale image as input
     */ {


        BufferedImage grayIm = new BufferedImage(img.getWidth(), img.getHeight(), type);
        Graphics2D g2 = grayIm.createGraphics();
        //g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);

        g2.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null);
        g2.dispose();

        return Utils.deepCopy(grayIm);
    }  // end of scaleGray()

    public static BufferedImage RGBnagrayscale(BufferedImage obrazek,int type) {
        BufferedImage obraz=new BufferedImage(obrazek.getWidth(), obrazek.getHeight(), type);
        for (int i = 0; i < obrazek.getWidth(); i++) {
            for (int j = 0; j < obrazek.getHeight(); j++) {
                int color = obrazek.getRGB(i, j);

                int alpha = (color >> 24) & 255;
                int red = (color >> 16) & 255;
                int green = (color >> 8) & 255;
                int blue = (color) & 255;

                final int lum = (int) (0.3 * red + 0.59 * green + 0.11 * blue);

                alpha = (alpha << 24);
                red = (lum << 16);
                green = (lum << 8);
                blue = lum;

                color = alpha + red + green + blue;
                obraz.setRGB(i, j, color);

            }
        }
        return obraz;
    }

    public BufferedImage rotacja(BufferedImage obrazek, int kat) {
        BufferedImage bufor_obrazu = null;
        Image obraz = obrazek;
        //odwracanie grafiki
        AffineTransform zmien = new AffineTransform();
        zmien.rotate(Math.toRadians(kat), obrazek.getWidth() / 2, obrazek.getHeight() / 2);


        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            //tworzenie buforowanego obrazu
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bufor_obrazu = gc.createCompatibleImage(obrazek.getWidth(), obrazek.getHeight());
        } catch (HeadlessException e) {
        }

        Graphics2D gg = bufor_obrazu.createGraphics();
        gg.transform(zmien);
        gg.drawImage(obraz, 0, 0, null);
        gg.dispose();

        return bufor_obrazu;
    }

    private BufferedImage wyrownanie_histogramu(BufferedImage obrazek) {
        int matryca[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        int alpha[][] = new int[obrazek.getWidth()][obrazek.getHeight()];

        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                int color = obrazek.getRGB(j, i);
                alpha[j][i] = (color >> 24) & 255;
                int lum = (color >> 16) & 255;
                int lum1 = (color >> 8) & 255;
                int lum2 = (color) & 255;
                int luminancja = (int) (0.3 * lum + 0.59 * lum1 + 0.11 * lum2);
                matryca[j][i] = luminancja;
            }
        }

        return obrazek;
    }

    public BufferedImage kontrast(BufferedImage obrazek, int antrybut) {
        int matryca[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        int alpha[][] = new int[obrazek.getWidth()][obrazek.getHeight()];

        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                int color = obrazek.getRGB(j, i);
                alpha[j][i] = (color >> 24) & 255;
                int lum = (color >> 16) & 255;
                int lum1 = (color >> 8) & 255;
                int lum2 = (color) & 255;
                int luminancja = (int) (0.3 * lum + 0.59 * lum1 + 0.11 * lum2);
                matryca[j][i] = luminancja;
            }
        }



        float antrybut1 = (float) antrybut / 100f;

        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                if (matryca[j][i] == 255) {
                }
                matryca[j][i] = (int) (antrybut1 * (matryca[j][i]));
            }
        }

//        for (int i = 0; i < obrazek.getHeight(); i++) {
//            for (int j = 0; j < obrazek.getWidth(); j++) {
//                if (matryca[j][i] > Ustawienia.wart_hist) {
//                    matryca[j][i] = 255;
//                }
//                if (matryca[j][i] < 0) {
//                    matryca[j][i] = 0;
//                }
//
//            }
//        }





        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {

                obrazek.setRGB(j, i, ((alpha[j][i] << 24) + matryca[j][i] << 16) + (matryca[j][i] << 8) + (matryca[j][i]));

            }
        }
        return obrazek;
    }

    public BufferedImage skalowanie(BufferedImage obrazek, float antrybut, float odleglosc) {

        float skala = antrybut / odleglosc;
        int w1 = obrazek.getWidth();
        int h1 = obrazek.getHeight();
        int nowy_rozmiar_szerokosc = (int) (skala * obrazek.getWidth());
        int nowy_rozmiar_wysokosc = (int) (skala * (float) obrazek.getHeight());
        int l1 = 0, l2 = 0;
        int[] tablica = new int[obrazek.getWidth() * obrazek.getHeight()];
        for (int y = 0; y < obrazek.getHeight(); y++) {
            for (int x = 0; x < obrazek.getWidth(); x++) {
                tablica[l1] = obrazek.getRGB(x, y);
                l1++;
            }
        }


        int w2 = nowy_rozmiar_szerokosc;
        int h2 = nowy_rozmiar_wysokosc;

        int[] tablica1 = new int[w2 * h2];
        int x_mnoznik = (int) ((w1 << 16) / w2);
        int y_mnoznik = (int) ((h1 << 16) / h2);
        int x2, y2;
        for (int i = 0; i < h2; i++) {
            for (int j = 0; j < w2; j++) {
                x2 = ((j * x_mnoznik) >> 16);
                y2 = ((i * y_mnoznik) >> 16);
                tablica1[(i * w2) + j] = tablica[(y2 * w1) + x2];
            }
        }


        BufferedImage img1 = new BufferedImage(nowy_rozmiar_szerokosc, nowy_rozmiar_wysokosc, BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < nowy_rozmiar_wysokosc; i++) {
            for (int j = 0; j < nowy_rozmiar_szerokosc; j++) {
                img1.setRGB(j, i, tablica1[l2]);
                l2++;
            }
        }
        return img1;
    }

    public BufferedImage wyrownanie_histogramu_normalizacja(BufferedImage obrazek) {
        final int liczba_odcieni = 255;
        int matryca[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        int alpha[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        int[] histogram = new int[liczba_odcieni + 1];
        float[] dystrybuanta = new float[liczba_odcieni];



        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                int color = obrazek.getRGB(j, i);
                alpha[j][i] = (color >> 24) & 255;
                int lum = (color >> 16) & 255;
                int lum1 = (color >> 8) & 255;
                int lum2 = (color) & 255;
                int luminancja = (int) (0.3 * lum + 0.59 * lum1 + 0.11 * lum2);
                matryca[j][i] = luminancja;
            }
        }
        //tworzenie histogramu
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {
                histogram[matryca[j][i]] = histogram[matryca[j][i]] + 1;
            }
        }
        //ilosc punkotw obrazu
        float ilosc_punktow = obrazek.getHeight() * obrazek.getWidth();

        //tworzenie dystrybuanty
        float pomocnik = 0;
        for (int j = 0; j < liczba_odcieni; j++) {
            pomocnik = pomocnik + (float) histogram[j];
            dystrybuanta[j] = (pomocnik / ilosc_punktow);

        }
        //pierwsz niezerowa wartosc dystrybuany
        float pierw_niezero_dyst = 0;
        for (int j = 0; j < liczba_odcieni; j++) {
            if (dystrybuanta[j] > 0) {
                pierw_niezero_dyst = dystrybuanta[j];
                break;
            }
        }


        int[] lut = new int[liczba_odcieni + 1];
        float wynik = 0;
        for (int j = 0; j < liczba_odcieni; j++) {
            wynik = (float) ((dystrybuanta[j] - pierw_niezero_dyst) / (float) (1 - pierw_niezero_dyst)) * (float) liczba_odcieni;

            lut[j] = (int) Math.ceil(wynik);

        }
        //zamiana kolorów
        int nowa_matryca[][] = new int[obrazek.getWidth()][obrazek.getHeight()];
        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {

                nowa_matryca[j][i] = lut[matryca[j][i]];

            }
        }

        for (int i = 0; i < obrazek.getHeight(); i++) {
            for (int j = 0; j < obrazek.getWidth(); j++) {

                obrazek.setRGB(j, i, ((alpha[j][i] << 24) + nowa_matryca[j][i] << 16) + (nowa_matryca[j][i] << 8) + (nowa_matryca[j][i]));

            }
        }
        return obrazek;
    }

    public BufferedImage tnij_obrazek(BufferedImage obrazek, int szerokosc, int gora, int dol) {
        szerokosc = (int) ((obrazek.getWidth() * szerokosc) / 100) / 2;
        gora = (int) ((obrazek.getHeight() * gora) / 100) / 2;
        dol = (int) (((obrazek.getHeight() - gora) * dol) / 100);
        try {

            obrazek = obrazek.getSubimage(szerokosc, gora, obrazek.getWidth() - (szerokosc * 2), obrazek.getHeight() - (dol + gora));
        } catch (RasterFormatException e) {


            JOptionPane.showMessageDialog(this, e, "Uwaga błąd", 0);
        }
        return obrazek;
    }

    public static class struktura_detekcja_oczu {

        BufferedImage obrazek;
        Point prawy;
        Point lewy;
        double kat;
        int odleglosc;

        struktura_detekcja_oczu() {
            prawy = new Point(0, 0);
            lewy = new Point(0, 0);
            obrazek = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
            kat = 0;
            odleglosc = 0;
        }
    }
}
